/**
 * Copyright 2000 self.com.au
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. (http://www.apache.org/licenses/LICENSE-2.0)
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
 * the specific language governing permissions and limitations under the License.
 *
 * <dhamma-message src="Atisha (11th century Tibetan Buddhist master)">
 * 	The greatest achievement is selflessness. The greatest worth is self-mastery.
 * 	The greatest quality is seeking to serve others. The greatest precept is continual awareness.
 * 	The greatest medicine is the emptiness of everything. The greatest action is not conforming with the worlds ways.
 * 	The greatest magic is transmuting the passions. The greatest generosity is non-attachment.
 * 	The greatest goodness is a peaceful mind. The greatest patience is humility.
 * 	The greatest effort is not concerned with results. The greatest meditation is a mind that lets go.
 * 	The greatest wisdom is seeing through appearances. 
 * </dhamma-message>
 *
 * @author Ashin Wimalajeewa
 */
package self.amigo.elem.bpm;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Map;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import self.amigo.elem.FillableFeature;
import self.amigo.elem.SymbolPaintManagerUtils;
import self.amigo.elem.uml.NameAndCompositionCompartmentsView;
import self.gee.IGraphicElement;
import self.lang.StringUtils;

public class HiFiArtifactView extends NameAndCompositionCompartmentsView {
	
	/**
	 * If the internal state of this class ever changes in such a way that it can't be defaulted,
	 * then the {@link #serialVersionUID} should be incremented to ensure serialized instances cleanly fail.  
	 */
	private static final long serialVersionUID = 1;
	
  final static public String FILL_PROP = "Fill";

  protected IGraphicElement createDelegate() {
    return new EssentialHiFiArtifactView();
  }

  class EssentialHiFiArtifactView extends AEssential {
  	
	/**
	 * If the internal state of this class ever changes in such a way that it can't be defaulted,
	 * then the {@link #serialVersionUID} should be incremented to ensure serialized instances cleanly fail.  
	 */
	private static final long serialVersionUID = 1;
	
    private FillableFeature  fillData = new FillableFeature();
    private Rectangle figDocument = new Rectangle(0,0,24,32);

    public EssentialHiFiArtifactView() {
      fillData.fillColor = new Color( 204, 204, 255 );
      fig.setBounds( 10, 10, 80, 20 );
      resetFrame();
    }

    protected void paintSymbolicRegion( Graphics surface ) {
      int[] xcoords = new int[5]; // w24,h32 (5)
      int[] ycoords = new int[5];
      xcoords[0] = figDocument.x;
      ycoords[0] = figDocument.y;
      xcoords[1] = xcoords[0] + 19;
      ycoords[1] = ycoords[0];
      xcoords[2] = xcoords[1] + 5;
      ycoords[2] = ycoords[0] + 5;
      xcoords[3] = xcoords[2] ;
      ycoords[3] = ycoords[0] + 32 ;
      xcoords[4] = xcoords[0];
      ycoords[4] = ycoords[3];

      if ( !outlineOnly ) {
        if (fillData.fillColor != null) {
          surface.setColor(fillData.fillColor);
          surface.fillPolygon( xcoords, ycoords, xcoords.length );
        }
      }
      surface.setColor(frameColor);
      surface.drawLine( xcoords[1], ycoords[1], xcoords[1], ycoords[1] + 5 );
      surface.drawLine( xcoords[1], ycoords[1] + 5, xcoords[2], ycoords[2] );
      surface.drawPolygon( xcoords, ycoords, xcoords.length );
      if ( !outlineOnly ) {
        surface.drawLine( xcoords[0] + 2, ycoords[0] + 4, xcoords[2] - 8, ycoords[0] + 4 );
        for ( int cntr = 0, lines = 0; lines < 8; cntr = cntr + 3, lines++ )
          surface.drawLine( xcoords[0] + 2, ycoords[0] + 8 + cntr, xcoords[2] - 3, ycoords[0] + 8 + cntr );
      }
    }

    public void       paint( Graphics surface ) {
      surface.setColor( frameColor );
      if ( !outlineOnly ) {
        String symbol = nameCompartment.aidLink;
        boolean paintSymbol = !StringUtils.isNullOrEmpty( symbol );
        if ( paintSymbol )
          SymbolPaintManagerUtils.startSymbol( surface, this, symbol );
        try {
          paintSymbolicRegion( surface );
        } finally {
          if ( paintSymbol )
            SymbolPaintManagerUtils.endSymbol( surface );
        }
      } else
        paintSymbolicRegion( surface );
      compartmentPainter.paint( surface, context, outlineOnly );
    }

    public void       resize( int x, int y, Point[] handle, MouseEvent e, int dragState ) {
      if ( dragState == IGraphicElement.DS_AFTER_LAST ) {
        super.resize( x, y, handle, e, dragState );
        return;
      }
      layer.beginUpdate();
      super.resize( x, y, handle, e, dragState );
      if ( fig.width < 80 )
        fig.width = 80;
      if ( fig.height < 20 )
        fig.height = 20;
      resetFrame();
      layer.endUpdate();
    }

    public void resetFrame() {
      figCompartment.setBounds( fig );

      if ( figDocument == null )
        return;

      figDocument.x = fig.x + (fig.width - figDocument.width)/2;
      figDocument.y = fig.y - figDocument.height;
    }

    public boolean    contains( Point within ) {
      boolean ret = fig.contains( within );
      if ( !ret )
        ret = figDocument.contains( within );
      return ret;
    }

    public boolean    isWithin( Rectangle within ) {
      boolean ret = fig.intersects( within );
      if ( !ret )
        ret = figDocument.intersects( within );
      return ret;
    }

    public Rectangle  getOverallBounds() {
      Rectangle ret = super.getOverallBounds();
      ret = ret.union( figDocument );
      return ret;
    }

    public boolean getLineIntersectionToCentre( int xFrom, int yFrom, int[] xyPoints ) {
      double[] xyP = new double[2];
      if ( yFrom <= fig.y ) {  // use shevron
        self.math.geom.RectangleUtils.getRectCentrePointIntersections( figDocument, xFrom, yFrom, xyP );
        xyPoints[0] = (int)xyP[0];
        xyPoints[1] = (int)xyP[1];
        return true;
      }
      Rectangle union = new Rectangle( fig );
      union.add( figDocument );
      self.math.geom.RectangleUtils.getRectCentrePointIntersections( union, xFrom, yFrom, xyP );
      xyPoints[0] = (int)xyP[0];
      xyPoints[1] = (int)xyP[1];
      return true;
    }

    // IEditableElement support
    public void       getProperties( Map store ) {
      super.getProperties( store );
      store.put( FILL_PROP, fillData.clone() );
    }

    public void       setProperties( Map data ) {
      super.setProperties( data );
      fillData.set( (FillableFeature) data.get(FILL_PROP) );
      layer.setDirty();
    }

    // IPersistentElement support
    public void readFrom( Node self, HashMap idObjLookUp ) throws DOMException {
      super.readFrom( self, idObjLookUp );
      fillData.readFrom( self, idObjLookUp );
    }

    public void writeTo( Document doc, Element self, HashMap objIdLookup ) throws DOMException {
      super.writeTo( doc, self, objIdLookup );
      fillData.writeTo( doc, self, objIdLookup );
    }
  }
}
